#ifndef GTL_DEBUG_HEADER_GUARD
#define GTL_DEBUG_HEADER_GUARD

#if defined(DEBUG) || defined(_DEBUG)
#define GTL_DEBUG
#endif

#include <cassert>
#include <cstdio>
#include <cstdarg>

inline void sprintf_def(char* dest, const char * format = 0, ...)
{
	if (!format) return;

	va_list args;
	va_start (args, format);
	vsprintf_s (dest, 1024, format, args);
	va_end (args);
}

#define GTL_BREAKPOINT __asm { __asm int 3 }

#ifdef GTL_DEBUG

#define GTL_ASSERT(condition, ...) \
	{ \
		if (! (condition)) { \
			char msg[1024] = ""; \
			sprintf_def(msg, __VA_ARGS__); \
			printf("Assertion `" #condition "` failed in %s line %i: %s\n", __FILE__, __LINE__, msg); \
			GTL_BREAKPOINT  \
		} \
	}
#else

#define GTL_ASSERT(a, ...) do { if (a) {} } while (false)

#endif

#define GTL_CRITICAL_FAILURE(...) \
	{ \
		char msg[1024] = ""; \
		sprintf_def(msg, __VA_ARGS__); \
		printf("Critical failure in %s line %i: %s\n", __FILE__, __LINE__, msg); \
		GTL_BREAKPOINT  \
	}


struct ErrorEnum
{
  int value;

  ErrorEnum() : value(0) {}
  ErrorEnum(const ErrorEnum& other) : value(other.value) {}
  ErrorEnum(int val) : value(val) {}

  ErrorEnum& operator=(const ErrorEnum& other) { value = other.value; return *this; }
  ErrorEnum& operator=(int val) { value = val; return *this; }

  operator int() const { return value; }
  operator bool() const { return !!value; }
};

#endif